/*
 * Licensed to Nanjing RedOrange Co. ltd (RedOrange) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * RedOrange licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */
package redora.rdo.html;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.owasp.validator.html.AntiSamy;
import org.owasp.validator.html.CleanResults;
import org.owasp.validator.html.Policy;
import org.owasp.validator.html.PolicyException;
import org.owasp.validator.html.ScanException;

import redora.rdo.exceptions.FieldException;

//TODO this might not perform very well, make a factory that caches the retrieve policies.

/**
 * AntiSamy HTML handler. Put in dirty HTML and clean HTML get's out.
 * @author Redora
 */
public class HtmlHandler {
	private static Logger l = Logger.getLogger("redora.rdo.html.HtmlHandler");

	public final static String MAX_INPUT_SIZE = "100000"; //65k + something extra.
	
	public static String clean(String policy, String in) throws FieldException {
		return clean(policy, in, MAX_INPUT_SIZE);
	}

	public static String clean(String policy, String in, String maxInputSize) throws FieldException {
		try {
			InputStream io = null;
			File f = new File("src" + File.separator + "main" + File.separator + "resources" + File.separator + "policies" + File.separator + policy);
			if (!f.exists()) {
				l.log(Level.INFO, "Did not find local policy, trying template policy");
				f = new File(".." + File.separator + "p-templates" + File.separator + "src" + File.separator + "main" + File.separator + "resources" + File.separator + "policies" + File.separator + policy);
			} else {
				l.log(Level.INFO, "Found local policy file");
			}
			if (f.exists()) {
				io = new FileInputStream(f);
			} else {
				l.log(Level.INFO, "Trying to retrieve the policy from the classpath");
				io = HtmlHandler.class.getResourceAsStream("/" + policy);
			}
		    Policy pol = Policy.getInstance(io);
		    AntiSamy as = new AntiSamy();
		    pol.setDirective(Policy.MAX_INPUT_SIZE, maxInputSize); //assuming a max size of 65k
		    CleanResults cr = as.scan(in, pol);
		    for (Object error : cr.getErrorMessages()) {
		      l.log(Level.INFO, "Message in html handling for antisamy: " + error);
		    }
		    return cr.getCleanHTML();
		} catch (PolicyException e) {
			throw new FieldException("Failed to set or find policy: " + policy, e);
		} catch (ScanException e) {
			throw new FieldException("Failed to scan html: " + in, e);
		} catch (FileNotFoundException e) {
			throw new FieldException("Unable to find policy file for: " + policy, e);
		}
	}
}
